package cn.mujiankeji.mbrowser.功能.下载.引擎

import android.app.DownloadManager
import android.content.Context
import android.net.Uri
import android.os.Environment
import android.util.Log
import cn.mujiankeji.mbrowser.功能.下载.模型.下载任务
import cn.mujiankeji.mbrowser.功能.下载.模型.下载状态
import cn.mujiankeji.mbrowser.功能.下载.模型.下载引擎类型
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import java.io.File

class SystemDownloadEngine(
    private val context: Context
) : 下载引擎接口 {

    private val TAG = "SystemDownloadEngine"
    private val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager

    // 用于存储我们内部任务ID与系统DownloadManager的ID之间的映射
    // 注意：这个映射的生命周期需要仔细管理，特别是当Service重启或Engine实例重建时。
    // 一种更健壮的方法是将 systemDownloadId 存储在 DownloadTask 持久化数据中。
    private val taskToSystemIdMap = mutableMapOf<String, Long>()
    private val systemIdToTaskMap = mutableMapOf<Long, String>()
    
    // 存储任务状态流
    private val taskStateFlows = mutableMapOf<String, MutableStateFlow<下载任务>>()


    override fun 开始下载(任务: 下载任务): Flow<下载任务> {
        val stateFlow = MutableStateFlow(任务)
        taskStateFlows[任务.id] = stateFlow
        
        // 启动下载操作
        try {
            val request = DownloadManager.Request(Uri.parse(任务.url))
            request.setTitle(任务.文件名)
            // request.setDescription("正在下载...") // 可选
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) // 或根据需求调整

            // 设置目标路径
            // 注意：DownloadManager 对目标路径有自己的处理方式，通常是公共下载目录。
            // 如果要精确控制到应用的内部或外部私有目录，需要更复杂的处理或直接使用 `setDestinationUri`
            // 这里我们先尝试保存到应用的公共下载目录下的一个子目录
            val destinationDir = File(
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
                "M浏览器" // 应用专属的子文件夹名
            )
            if (!destinationDir.exists()) {
                destinationDir.mkdirs()
            }
            val destinationFile = File(destinationDir, 任务.文件名)
            request.setDestinationUri(Uri.fromFile(destinationFile)) // 推荐使用此方法以精确控制路径

            // 添加请求头
            任务.请求头.forEach { (key, value) ->
                request.addRequestHeader(key, value)
            }
            if (任务.UserAgent != null) {
                request.addRequestHeader("User-Agent", 任务.UserAgent)
            }

            val systemDownloadId = downloadManager.enqueue(request)
            taskToSystemIdMap[任务.id] = systemDownloadId
            systemIdToTaskMap[systemDownloadId] = 任务.id

            Log.i(TAG, "任务 ${任务.id} 已加入系统下载队列，系统ID: $systemDownloadId, 文件名: ${任务.文件名}")

            // 更新任务状态
            val updatedTask = 任务.copy(状态 = 下载状态.正在下载)
            stateFlow.value = updatedTask
            
        } catch (e: Exception) {
            Log.e(TAG, "系统下载请求失败 for ${任务.id}: ${e.message}", e)
            val errorTask = 任务.copy(状态 = 下载状态.失败, 错误信息 = e.localizedMessage ?: "请求系统下载失败")
            stateFlow.value = errorTask
        }
        
        return stateFlow
    }

    override suspend fun 暂停下载(任务Id: String) {
        Log.w(TAG, "暂停下载 ($任务Id): Android DownloadManager 不直接支持暂停操作。通常是取消然后由用户决定是否续传（如果系统支持）。")
        // Android的DownloadManager没有直接的API来暂停一个正在进行的下载。
        // 某些OEM实现可能有，但标准API没有。
        // 最接近的是取消下载，然后如果用户再次下载相同URL，系统可能会尝试续传。
        
        val systemId = taskToSystemIdMap[任务Id]
        if (systemId != null) {
            // 实际无法暂停，但我们可以模拟这个状态
            Log.d(TAG, "模拟暂停任务 $任务Id (System ID: $systemId)")
            
            // 更新任务状态
            taskStateFlows[任务Id]?.let { stateFlow ->
                val currentTask = stateFlow.value
                stateFlow.value = currentTask.copy(状态 = 下载状态.已暂停)
            }
        }
    }

    override fun 恢复下载(任务: 下载任务): Flow<下载任务> {
        Log.w(TAG, "恢复下载 (${任务.id}): Android DownloadManager 不直接支持恢复操作。")
        // 类似于暂停，没有直接的API。
        // 如果任务之前被"取消"（例如模拟暂停），并且源文件和URL支持，
        // 重新enqueue一个相同的请求可能实现续传。
        
        // 尝试查找已存在的状态流
        val existingStateFlow = taskStateFlows[任务.id]
        if (existingStateFlow != null) {
            // 更新为正在下载状态
            val updatedTask = 任务.copy(状态 = 下载状态.正在下载)
            existingStateFlow.value = updatedTask
            return existingStateFlow
        } 
        
        // 如果没有找到，创建新的下载
        return 开始下载(任务.copy(状态 = 下载状态.等待中))
    }

    override suspend fun 取消下载(任务Id: String) {
        val systemId = taskToSystemIdMap[任务Id]
        if (systemId != null) {
            val count = downloadManager.remove(systemId)
            if (count > 0) {
                Log.i(TAG, "已从系统下载器取消任务 $任务Id (System ID: $systemId)")
                taskToSystemIdMap.remove(任务Id)
                systemIdToTaskMap.remove(systemId)
                
                // 更新任务状态
                taskStateFlows[任务Id]?.let { stateFlow ->
                    val currentTask = stateFlow.value
                    stateFlow.value = currentTask.copy(状态 = 下载状态.已取消)
                    // 可以选择是否从状态流集合中移除
                    // taskStateFlows.remove(任务Id)
                }
            } else {
                Log.w(TAG, "取消系统任务 $任务Id (System ID: $systemId) 失败或任务已不存在")
            }
        } else {
            Log.w(TAG, "未找到要取消的系统任务 $任务Id")
        }
    }

    override suspend fun 查询下载状态(任务Id: String): 下载任务? {
        val systemId = taskToSystemIdMap[任务Id] ?: return null
        
        val query = DownloadManager.Query().setFilterById(systemId)
        val cursor = downloadManager.query(query)

        if (cursor != null && cursor.moveToFirst()) {
            val statusColumn = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
            val reasonColumn = cursor.getColumnIndex(DownloadManager.COLUMN_REASON)
            val bytesDownloadedColumn = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
            val bytesTotalColumn = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
            val localUriColumn = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI) // 下载完成后的文件URI

            val systemStatus = cursor.getInt(statusColumn)
            val bytesDownloaded = cursor.getLong(bytesDownloadedColumn)
            val bytesTotal = cursor.getLong(bytesTotalColumn)
            val localUri = cursor.getString(localUriColumn)

            val mappedStatus = mapSystemStatusToDomain(systemStatus)
            val reason = cursor.getInt(reasonColumn) // Provides more details on errors

            // 获取当前任务信息，更新状态
            val currentTask = taskStateFlows[任务Id]?.value
            cursor.close()
            
            return currentTask?.copy(
                状态 = mappedStatus,
                已下载大小 = bytesDownloaded,
                文件大小 = bytesTotal.takeIf { it > 0 } ?: currentTask.文件大小,
                错误信息 = if (mappedStatus == 下载状态.失败) "System Error: $reason" else null
            )
        } else {
            cursor?.close()
            Log.w(TAG, "查询系统任务 $任务Id (System ID: $systemId) 时未找到Cursor或Cursor为空")
            return taskStateFlows[任务Id]?.value
        }
    }

    /**
     * 将系统下载管理器的状态转换为应用定义的下载状态
     * 
     * @param systemStatus 系统下载管理器的状态码
     * @return 应用定义的下载状态
     */
    private fun mapSystemStatusToDomain(systemStatus: Int): 下载状态 {
        return when (systemStatus) {
            DownloadManager.STATUS_PENDING -> 下载状态.等待中
            DownloadManager.STATUS_RUNNING -> 下载状态.正在下载
            DownloadManager.STATUS_PAUSED -> 下载状态.已暂停 // 系统层面可能因为等待网络、重试等暂停
            DownloadManager.STATUS_SUCCESSFUL -> 下载状态.已完成
            DownloadManager.STATUS_FAILED -> 下载状态.失败
            else -> 下载状态.失败 // 或其他未知状态
        }
    }

    fun getEngineType(): 下载引擎类型 {
        return 下载引擎类型.系统下载器
    }

    suspend fun shutdown() {
        // 对于系统下载器，通常不需要显式关闭，因为它由系统管理。
        // 清理本地映射表（如果不再需要）
        taskToSystemIdMap.clear()
        systemIdToTaskMap.clear()
        taskStateFlows.clear()
        Log.d(TAG, "SystemDownloadEngine shutdown.")
    }
} 